#include "HY1C_out.h"
#include "l12_proto.h"
#include "scene_meta.h"




int HY1C_SetI16GA(idDS ds_id, char *name, int32 value) {
  if ( ds_id.fftype == FMT_L1HDF || ds_id.fftype == FMT_L2HDF
       || ds_id.fftype == FMT_L3BIN) {
    PTB( sd_setattr(ds_id.fid, name, DFNT_INT16, 1, (VOIDP)&value)       );
  } else if ( ds_id.fftype == FMT_L2NCDF) {
    int status;
    status = nc_put_att_int(ds_id.fid, NC_GLOBAL, name,
                NC_SHORT, 1, (const short *) &value);
    if( status != NC_NOERR) {
      printf("-E- %s %d: %s for %s\n",
         __FILE__, __LINE__, nc_strerror(status), name);
      exit(1);
    }
  } else {
      printf("-E- %s %d fftype not defined\n", __FILE__, __LINE__);
      exit(1);
  }
  return(LIFE_IS_GOOD);
}


/*
int HY1C_SetI32GA(idDS ds_id, char *name, int32 value) {
  if ( ds_id.fftype == FMT_L1HDF || ds_id.fftype == FMT_L2HDF
       || ds_id.fftype == FMT_L3BIN) {
    PTB( sd_setattr(ds_id.fid, name, DFNT_INT32, 1, (VOIDP)&value)       );
  } else if ( ds_id.fftype == FMT_L2NCDF) {
    int status;
    status = nc_put_att_int(ds_id.fid, NC_GLOBAL, name,
                NC_INT, 1, (const int32 *) &value);
    if( status != NC_NOERR) {
      printf("-E- %s %d: %s for %s\n",
         __FILE__, __LINE__, nc_strerror(status), name);
      exit(1);
    }
  } else {
      printf("-E- %s %d fftype not defined\n", __FILE__, __LINE__);
      exit(1);
  }
  return(LIFE_IS_GOOD);
}

*/





static scnstr meta;

static int   first        = 1;
static int   second       = 1;
static int   centerfound  = 0;
static int   start_node   = UNKNOWNNODE;
static int   end_node     = UNKNOWNNODE;
static int   ascdsc       = UNKNOWNNODE;
static int   daynight     = UNKNOWNSCENE;
static float lastLat      = -999;
static float lastLon0     = -999;
static float lastLonN     = -999;
static int   lastScan     = -1;
static float northern_lat =  -90.0;
static float southern_lat =  +90.0;
static float eastern_lon  = -180.0;
static float western_lon  = +180.0;

static float lat_rec[10] = 
      { -999., -999., -999., -999., -999., -999., -999., -999., -999., -999, };
static int lat_rec_ptr = 0;

static char *nodestr    [3] = {"Ascending","Descending","Unknown"};
static char *daynightstr[4] = {"Day","Night","Mixed","Unknown"};

float32 westernmost( float32 lon1, float32 lon2 )
{
    if (lon1 == -999.) lon1 = lon2;

    if ( fabs(lon1 - lon2) < 190.0 )
        return ( MIN(lon1,lon2) );
    else
        return ( MAX(lon1,lon2) );
}


float32 easternmost( float32 lon1, float32 lon2 )
{
    if (lon1 == -999.) lon1 = lon2;

    if ( fabs(lon1 - lon2) < 190.0 )
        return ( MAX(lon1,lon2) );
    else
        return ( MIN(lon1,lon2) );
}

void scene_meta_init(void)
{
    strcpy(meta.daynight,daynightstr[UNKNOWNSCENE]);
    strcpy(meta.start_node,nodestr[UNKNOWNNODE]);
    strcpy(meta.end_node,nodestr[UNKNOWNNODE]);
    strcpy(meta.start_time,"");
    strcpy(meta.center_time,"");
    strcpy(meta.end_time,"");

    meta.start_year      = 0;
    meta.start_day       = 0;
    meta.start_msec      = 0;

    meta.end_year        = 0;
    meta.end_day         = 0;
    meta.end_msec        = 0;

    meta.northern_lat    =   90.0;
    meta.southern_lat    =  -90.0;
    meta.eastern_lon     =  180.0;
    meta.western_lon     = -180.0;

    meta.upperleft_lon   = -180.0;
    meta.upperright_lon  =  180.0;
    meta.upperleft_lat   =   90.0;
    meta.upperright_lat  =   90.0;

    meta.lowerleft_lon   = -180.0;
    meta.lowerright_lon  =  180.0;
    meta.lowerleft_lat   =   90.0;
    meta.lowerright_lat  =   90.0;

    meta.start_center_lon   = 0.0;
    meta.start_center_lat   = 0.0;
    meta.scene_center_lon   = 0.0;
    meta.scene_center_lat   = 0.0;
    meta.scene_center_solz  = 0.0;
    meta.end_center_lon     = 0.0;
    meta.end_center_lat     = 0.0;
}

void scene_meta_put(l1str *l1rec)
{
    static int firstCall = 1;
    static int32_t cscan;

    int32_t cpix  = l1rec->npix/2;
    int32_t npix  = l1rec->npix;
    float64 utime = 0;
    int32_t ip;

    if (firstCall) {
        firstCall = 0;
	scene_meta_init();
        cscan = l1rec->sscan + (l1rec->escan-l1rec->sscan+1)/2;
    }

    /* ignore buffering scans */
    if (l1rec->iscan == lastScan) return;
    if (l1rec->iscan < l1rec->sscan) return;
    if (l1rec->iscan > l1rec->escan) return;

    if ((l1rec->flags[     0] & NAVFAIL) == 0 &&
        (l1rec->flags[  cpix] & NAVFAIL) == 0 &&
        (l1rec->flags[npix-1] & NAVFAIL) == 0) {

      if (first) {

          first = 0;
          northern_lat = l1rec->lat[cpix];
          southern_lat = l1rec->lat[cpix];
          daynight = UNKNOWNSCENE;

          meta.upperleft_lon  = l1rec->lon[0];
          meta.upperright_lon = l1rec->lon[npix-1];
          meta.upperleft_lat  = l1rec->lat[0];
          meta.upperright_lat = l1rec->lat[npix-1];
          meta.start_center_lon = l1rec->lon[cpix];
          meta.start_center_lat = l1rec->lat[cpix];
          meta.start_year = *(l1rec->year);
          meta.start_day  = *(l1rec->day);
          meta.start_msec = *(l1rec->msec);
          utime = yds2unix(*l1rec->year,*l1rec->day,((double)(*l1rec->msec))/1000.0);
          strcpy(meta.start_time,ydhmsf(utime,'G'));

      } else if (second) {

          second = 0;
          if (l1rec->lat[cpix] > lastLat)
            ascdsc = 0; /* Ascending  */  
          else
            ascdsc = 1; /* Descending */
          start_node   = ascdsc;
          end_node     = ascdsc;

          ascdsc = ( l1rec->sensorID == CZCS ) ? 1 - ascdsc : ascdsc;
          if (ascdsc == 1) {              /* Descending */
              western_lon = westernmost(lastLon0,l1rec->lon[0]);
              eastern_lon = easternmost(lastLonN,l1rec->lon[npix-1]);
          } else {                        /* Ascending */
              western_lon = westernmost(lastLonN,l1rec->lon[npix-1]);
              eastern_lon = easternmost(lastLon0,l1rec->lon[0]);
          }

      } else {

          if (l1rec->lat[cpix] > lastLat)
            ascdsc = 0; /* Ascending  */  
          else
            ascdsc = 1; /* Descending */
          end_node = ascdsc;

          ascdsc = ( l1rec->sensorID == CZCS ) ? 1 - ascdsc : ascdsc;
          if (ascdsc == 1) {              /* Descending */
              western_lon  = westernmost(western_lon,l1rec->lon[0]);
              eastern_lon  = easternmost(eastern_lon,l1rec->lon[npix-1]);
          } else {                        /*Ascending */
              western_lon  = westernmost(western_lon,l1rec->lon[npix-1]);
              eastern_lon  = easternmost(eastern_lon,l1rec->lon[0]);
          }

          meta.lowerleft_lon  = l1rec->lon[0];
          meta.lowerright_lon = l1rec->lon[npix-1];
          meta.lowerleft_lat  = l1rec->lat[0];
          meta.lowerright_lat = l1rec->lat[npix-1];
          meta.end_center_lon = l1rec->lon[cpix];
          meta.end_center_lat = l1rec->lat[cpix];
//          meta.end_year = *(l1rec->year);
//          meta.end_day  = *(l1rec->day);
//          meta.end_msec = *(l1rec->msec);
          meta.end_year = *(l1rec->year);
          meta.end_day  = *(l1rec->day);
          meta.end_msec = *(l1rec->msec);
          utime = yds2unix(*l1rec->year,*l1rec->day,((double)(*l1rec->msec))/1000.0);
          strcpy(meta.end_time,ydhmsf(utime,'G'));
      }

      if (l1rec->iscan >= cscan && !centerfound) {
          meta.scene_center_lon  = l1rec->lon[cpix];
          meta.scene_center_lat  = l1rec->lat[cpix];
          meta.scene_center_solz = l1rec->solz[cpix];
          utime = yds2unix(*l1rec->year,*l1rec->day,((double)(*l1rec->msec))/1000.0);
          strcpy(meta.center_time,ydhmsf(utime,'G'));
          centerfound = 1;
      }

      for (ip=0; ip<npix; ip++) {
          if ((l1rec->flags[ip] & NAVFAIL) == 0) {
              northern_lat = MAX(northern_lat,l1rec->lat[ip]);
              southern_lat = MIN(southern_lat,l1rec->lat[ip]);
              if (daynight != DAYANDNIGHT) {
	          if (l1rec->solz[ip] > SOLZNIGHT) {
                      if (daynight == DAYSCENE)
		          daynight = DAYANDNIGHT;
		      else
		          daynight = NIGHTSCENE;
   	          } else {
                      if (daynight == NIGHTSCENE)
		          daynight = DAYANDNIGHT;
		      else
		          daynight = DAYSCENE;
	          }
	      }
          }
      }

      if( lat_rec[lat_rec_ptr] > -100. )
          lastLat = lat_rec[lat_rec_ptr];
      else
          lastLat = l1rec->lat[cpix];
      lat_rec[lat_rec_ptr++] = l1rec->lat[cpix];
      lat_rec_ptr = lat_rec_ptr % 10;
      lastLon0 = l1rec->lon[0];
      lastLonN = l1rec->lon[npix-1];
      lastScan = l1rec->iscan;

      strcpy(meta.start_node,nodestr[start_node]);
      strcpy(meta.end_node,nodestr[end_node]);
      strcpy(meta.daynight,daynightstr[daynight]);

      meta.northern_lat = northern_lat; 
      meta.southern_lat = southern_lat; 
      meta.eastern_lon  = eastern_lon; 
      meta.western_lon  = western_lon; 
    }

}

scnstr *scene_meta_get(void)
{
  return(&meta);
}









void scene_meta_write(idDS ds_id)
{
    scnstr *m = &meta;

    SetChrGA(ds_id, "Start Time",    m->start_time);
    //20180828   NCDF  NEED IT!!
    HY1C_SetI16GA(ds_id, "Start Year",    m->start_year);
    HY1C_SetI16GA(ds_id, "Start Day",     m->start_day );
   HY1C_SetI32GA(ds_id, "Start Millisec",m->start_msec);

//    SetF32GA(ds_id, "Upper Left Longitude",  m->upperleft_lon);
//    SetF32GA(ds_id, "Upper Right Longitude", m->upperright_lon);
//    SetF32GA(ds_id, "Upper Left Latitude",   m->upperleft_lat);
//    SetF32GA(ds_id, "Upper Right Latitude",  m->upperright_lat);

//    SetF32GA(ds_id, "Start Center Longitude",m->start_center_lon);
//    SetF32GA(ds_id, "Start Center Latitude" ,m->start_center_lat);

    SetChrGA(ds_id, "Latitude Units", "degrees North");
    SetChrGA(ds_id, "Longitude Units","degrees East" );

//    SetChrGA(ds_id, "Scene Center Time", m->center_time);
//    SetF32GA(ds_id, "Scene Center Longitude",m->scene_center_lon);
//    SetF32GA(ds_id, "Scene Center Latitude" ,m->scene_center_lat);
//    SetF32GA(ds_id, "Scene Center Solar Zenith",m->scene_center_solz);

//    SetChrGA(ds_id, "End Time",     m->end_time);
//    SetI16GA(ds_id, "End Year",     m->end_year);
//    SetI16GA(ds_id, "End Day",      m->end_day );
//    SetI32GA(ds_id, "End Millisec", m->end_msec);

//    SetF32GA(ds_id, "Lower Left Longitude",  m->lowerleft_lon);
//    SetF32GA(ds_id, "Lower Right Longitude", m->lowerright_lon);
//    SetF32GA(ds_id, "Lower Left Latitude",   m->lowerleft_lat);
//    SetF32GA(ds_id, "Lower Right Latitude",  m->lowerright_lat);

//    SetF32GA(ds_id, "End Center Longitude",m->end_center_lon);
//    SetF32GA(ds_id, "End Center Latitude" ,m->end_center_lat);

//    SetF32GA(ds_id, "Northernmost Latitude", m->northern_lat);
//    SetF32GA(ds_id, "Southernmost Latitude", m->southern_lat);
//    SetF32GA(ds_id, "Easternmost Longitude", m->eastern_lon);
//    SetF32GA(ds_id, "Westernmost Longitude", m->western_lon);

//    SetChrGA(ds_id, "Start Node", m->start_node);
//    SetChrGA(ds_id, "End Node",   m->end_node);
//    SetChrGA(ds_id, "Day or Night",m->daynight);
}
